/*
 * =====================================================================================
 *
 *       Filename:  mj_stdio.c
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  2009-6-10 23:07:37
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YinLubin
 *        Company:  
 *
 * =====================================================================================
 */

#include "osUser.h"
#include "project.h"
#include <ctype.h>

#include "stdio_gui.h"

static int max_cursor_x = 53;
static int max_cursor_y = 20;

static struct {
	int x;
	int y;
} curCursor = {1, 1}, curPixel = {0, 0};

static struct {
	int width;
	int height;
} curFontSize = {8, 16};

// int curr;
// MEvent pEvent;


void UpdateCurFontSize(void);
void FlushStd(void);

/**
 * move current cursor x
 */
void MoveCursorX(int dx)
{
	 curCursor.x += dx;
	if (curCursor.x > max_cursor_x) {
		curCursor.y += (curCursor.x / max_cursor_x);
		curCursor.x += (curCursor.x % max_cursor_x);
	}
	if (curCursor.x == 0) {
		curCursor.x = max_cursor_x;
		--curCursor.y;
	}

	if (curCursor.y < 1) {
		curCursor.y = 1;
	}

	if (curCursor.y > max_cursor_y) {
		FlushStd();
		curCursor.y = max_cursor_y;
	}

	// calculate pixel from cursor
	curPixel.x = (curCursor.x-1)*(curFontSize.width); 
	curPixel.y = (curCursor.y-1)*(curFontSize.height);
}
/**
 * move current cursor y
 */
void MoveCursorY(int dy)
{
	curCursor.x = 1;
	curCursor.y += dy;
	if (curCursor.y > max_cursor_y) {
		FlushStd();
		curCursor.y = max_cursor_y;
	}
	if (curCursor.y <1 ) {
		curCursor.y = 1;
	}

	// calculate pixel from cursor
	curPixel.x = (curCursor.x-1)*(curFontSize.width); 
	curPixel.y = (curCursor.y-1)*(curFontSize.height);
}


/**
 * Get character size of current font
 */
void UpdateCurFontSize()
{
	UINT16 d = GraphGetFontLibID(NULL);
	switch (d) {
		case 12:
			curFontSize.height = 12;
			curFontSize.width = 6;
			break;
		case 16:
			curFontSize.height = 16;
			curFontSize.width = 8;
			break;
		case 24:
			curFontSize.height = 24;
			curFontSize.width = 12;
			break;
		default:
			break;
	}
}

/**
 * write buffer to stdout
 */
int os_stdout_write(char *buf, int nbyte)
{
	os_puts(buf);
	return strlen(buf);
}

/**
 * write buffer to stderr
 */
int os_stderr_write(char *buf, int nbyte)
{
	os_puts(buf);
	return strlen(buf);
}

/**
 * Display string
 * @attention: only for English output
 */
int os_puts(const char *str)
{
	const char *ptr;
	char str1[100];		// this should be always enough for buffer of a line
	int len;
	int last;
	int outLen = strlen(str);
//	char sdc[100];

//	sprintf(sdc,"%d",MemGetSpareSize());
	
	if (!strcmp(str,"\n")) {
		MoveCursorY(1);
		return outLen;
	}
//	GraphDrawText(NULL, 0, 0, 320, 160, NULL, sdc);

	ptr=str;
	UpdateCurFontSize();
	while (1) {
		len=strlen(ptr);
		last = max_cursor_x - curCursor.x + 1;

		//	printf("len=%d last=%d\n",len,last);
		if (last==0) {
			return outLen;
		}
		if (len<=last) {
			//	printf("prepare to print <%s> at %d,%d \n",ptr,(curPixel.x),(curPixel.y));
			GraphDrawText(NULL, (curPixel.x), (curPixel.y), 0, 0, NULL, (char*)ptr);
			MoveCursorX(len);
			return outLen;
		}
		strncpy(str1,ptr,last); str1[last+1]='\0';
		GraphDrawText(NULL, (curPixel.x), (curPixel.y), 0, 0, NULL, str1);
		ptr+=last;
		MoveCursorY(1);
	}
}

/**
 * Display string
 * This is implemented by printing character by character
 * @attention: only for English output
 */
int os_puts_(const char * str)
{
	char oneCharStr[2] = {0};	// string for 1 character
	int outLen = 0;		// length of outputed string
	for (;*str != '\0'; ++str) {
		++outLen;
		switch (*str) {
			case '\n':
				MoveCursorY(1);
				break;
			case '\t':
				MoveCursorX(4);
				break;
			default:
				oneCharStr[0] = *str;
				oneCharStr[1] = '\0';
				GraphDrawText(NULL, curPixel.x, curPixel.y, 0, 0, NULL, oneCharStr);
				MoveCursorX(1);
				break;
		}
	}
	return outLen;
}

void FlushStd()
{
//	printf("run FlushStd()\n");
	GraphBitBlt(NULL, 0, 0, NULL, 0, (curFontSize.height), 320, 240-(curFontSize.height));
	GraphClearRect(NULL, 0, 240-(curFontSize.height)+1, 320, 240);
	return;
}

int my_gets(char *linebuffer,int maxlong)
{
	int curr;
    MEvent pEvent;
	char str[2];
	int cur_state;
	UINT8 byDrawMode;

	linebuffer[maxlong -1] = '\0';

	if (maxlong==0) {
		return 0;
	}
//	printf("run my_fgets");
	cur_state=1;
	curr=0;

//	printf("%d,%d\n",cur_x,cur_y);
	while (1) 
	{
		MsgGet(&pEvent);
		if (pEvent.dwMsgType==0x10 && isprint(pEvent.xParam)) 
		{//字母处理
			pEvent.xParam=A2s((char)pEvent.xParam);

			if (curr>=maxlong) return maxlong;
			str[0]=pEvent.xParam;
			str[1]=0;
			sprintf(str,"%c",pEvent.xParam);
//			printf("---%d,%d----\n",cur_x,cur_y);
			GraphDrawText(NULL, (curPixel.x), (curPixel.y), 0, 0, NULL, str);
//			printf("%c",str[1]);
			linebuffer[curr]=pEvent.xParam;

//			GraphSetDrawMode(NULL, DRMODE_WHITENESS);		//清光标
//			GraphDrawLine(NULL, (curPixel.x), (curPixel.y), (curPixel.x), (curPixel.y)+(curFontSize.height)-1);

			curr+=1;
//			if (cur_state==-1) { //反显光标
//				GraphDrawLine(NULL, (curPixel.x), (curPixel.y), (curPixel.x), (curPixel.y)+(curFontSize.height));
//				cur_state=1;
//			}
			MoveCursorX(1);
		}
		if (pEvent.dwMsgType==0x2000 && pEvent.xParam==0x1c00)
		{
			
			byDrawMode=GraphGetDrawMode(NULL);
			GraphSetDrawMode(NULL, DRMODE_SRCXOR);
			GraphDrawLine(NULL, (curPixel.x), (curPixel.y), (curPixel.x), (curPixel.y)+(curFontSize.height)-1);
			GraphSetDrawMode(NULL, byDrawMode);
			cur_state=-cur_state;
		}
		if (pEvent.dwMsgType==0x10 && pEvent.xParam==0x0d) 
		{
//			printf("end\n");
			linebuffer[curr++]='\n';

			GraphClearRect(NULL, (curPixel.x), (curPixel.y), (curPixel.x), (curPixel.y)+(curFontSize.height)-1);	//清光标
			MoveCursorY(1);

			if (curr<maxlong)
			{
				linebuffer[curr]=0;
				return strlen(linebuffer);
			}
			else
				return maxlong;
		}
		if (pEvent.dwMsgType==0x10 && pEvent.xParam==0x89 && curr>0)	//退格？
		{
			GraphClearRect(NULL, (curPixel.x), (curPixel.y), (curPixel.x)+(curFontSize.width), (curPixel.y)+(curFontSize.height));
			MoveCursorX(-1);
			GraphClearRect(NULL, (curPixel.x), (curPixel.y), (curPixel.x)+(curFontSize.width), (curPixel.y)+(curFontSize.height));
			cur_state=1;
			curr-=1;
		}
	}	//while 1

}

void EventScan(sEvent *e)
{
	MEvent pEvent;
	MsgGet(&pEvent);

	e->type=pEvent.dwMsgType;
	e->xp=pEvent.xParam;
	e->yp=pEvent.yParam;
}

void CurInit() /* initialize curses */
{
	static initialized = FALSE;
	UINT16 FontLibID;

	if (FALSE != initialized) {
		return;
	}

	FontLibID=GraphGetFontLibID(NULL);
	if (FontLibID==SYSFONT_GBK12) 
	{
		max_cursor_x=53;
		max_cursor_y=20;
	}
	if (FontLibID==SYSFONT_GBK16) 
	{
//		max_cursor_x=40;
//		max_cursor_y=13;
		max_cursor_x=53;
		max_cursor_y=16;
	}
	if (FontLibID==SYSFONT_GBK24) 
	{
		max_cursor_x=26;
		max_cursor_y=9;
	}

	initialized = TRUE;
}

/**
 * Initialize std stream
 */
void StdInit()
{
	UpdateCurFontSize();
	CurInit();
}

void cls()
{
	GraphClearScreen();
	curCursor.x = 1;
	curCursor.y = 1;
}

/**
 * Convert upper alphabet to symbol
 */
char A2s(char c)
{
	const char s4A[] =
	{	
		'[',	//A
		'#',	//B
		'`',	//C
		']',	//D
		'%',	//E
		'_',	//F
		';',	//G
		'\"',	//H
		'-',	//I
		'<',	//J
		'>',	//K
		'=',	//L
		':',	//M
		'$',	//N
		'*',	//O
		'/',	//P
		'{',	//Q
		'&',	//R
		'\\',	//S
		'^',	//T
		'+',	//U
		'~',	//V
		'}',	//W
		'|',	//X
		'.',	//Y
		'Z',	//Z
	};

	if (c>='A' && c<='Z')
		return s4A[c-'A'];
	else
		return c;
}

